#include "EquationSolver.h"
const double pi =3.141592654;

// homework B
class F1 : public Function{
public:
    double operator () (const double &x) const{
        return 1.0/x-tan(x);
    }
} f1;

void test1(){
    BisectionSolver solver(0,pi/2,f1);
    double root = solver.solve();
    cout << "Programme B" << endl;
    cout << " " << endl;
    cout << "root of 1/x-tan(x) in [0,pi/2] = "<<root <<endl;
}


class F2 : public Function{
public:
    double operator () (const double &x) const{
        return 1.0/x-pow(2,x);
    }
} f2;

void test2(){
    BisectionSolver solver(0,1,f2);
    double root = solver.solve();
    cout << "root of  1/x-2^(x) = "<<root <<endl;
}


class F3 : public Function{
public:
    double operator () (const double &x) const{
        return pow(2,x)+exp(x)+2*cos(x)-6;
    }
} f3;

void test3(){
    BisectionSolver solver(1,3,f3);
    double root = solver.solve();
    cout << "root of pow(2,x)+exp(x)+2*cos(x)-6 = "<<root <<endl;
}


class F4 : public Function{
public:
    double operator () (const double &x) const{
        return (x*x*x+4*x*x+3*x+5)/(2*x*x*x-9*x*x+18*x-2);
    }
} f4;

void test4(){
    BisectionSolver solver(0,4,f4);
    double root = solver.solve();
    cout << "root of (x^3+4x^2+3x+5)/(2x^3-9x^2+18x-2) = "<<root <<endl;
    cout << " " << endl;
}



// homework C
class Fc1 : public Function{
public:
    double operator () (const double &x) const{
        return x- tan(x);
    }
} fc1;

void test_c_1(){
    NewtonSolver solver1(4.5,fc1);
    NewtonSolver solver2(7.7,fc1);
    double root1 = solver1.solve();
    double root2 = solver2.solve();
    cout << " Programme C " << endl;

    cout << "roots of x=tan(x) near 4.5 ="<<root1 <<endl;
    cout << "roots of x=tan(x) near 7.7 ="<<root2 <<endl;
    cout << " " << endl;
}




//homework D
class Fd1 : public Function{
public:
    double operator() (const double &x) const{
        return sin(x/2)-1;
    }
} fd1;

void test_d_1(){
    SecandSolver solver(0,pi/2,fd1);
    double root = solver.solve();
    cout << "Programme D " << endl;
    cout << " " <<endl;
    cout << "root of  sin(x/2)-1 = " << root << endl;
}


class Fd2 : public Function{
public:
    double operator() (const double &x) const{
        return exp(x)-tan(x);
    }
} fd2;

void test_d_2(){
    SecandSolver solver(1,1.4,fd2);
    double root = solver.solve();
    cout << "root of e^x-tan(x) = " << root << endl;
}


class Fd3 : public Function{
public:
    double operator() (const double &x) const{
        return x*x*x -12*x*x +3*x +1;
    }
} fd3;

void test_d_3(){
    SecandSolver solver(0,-0.5,fd3);
    double root = solver.solve();
    cout << "root of x^3-12x^2+3x+1 = " << root << endl;
    cout << " " << endl;
}




//homework E
const double L =10, r =1, V =12.4;

class Fe : public Function{
public:
    double operator () (const double &h) const{
        return L * ( 0.5*pi*r*r - r*r*asin(h/r) - h*sqrt(r*r - h*h))-V;
    }
    double diff (const double &h) const{
        return L*(-r*1/ sqrt(1.0 -(h/r)*(h/r)) - sqrt(r*r - h*h ) + 2*h*h/ sqrt(r*r -h*h) );
    }
} fe;

void test_e()
{
    BisectionSolver solver1(0,1,fe);
    double root1= solver1.solve();
    NewtonSolver solver2(0,fe);
    double root2 = solver2.solve();
    SecandSolver solver3(0,1,fe);
    double root3 = solver3.solve();
    cout << "Programme E" <<endl;
    cout << "BisectionSolver "<< root1 << endl;
    cout << "Newton's method "<< root2 << endl;
    cout << "Secand method "<< root3 << endl;
    cout << " " << endl;
}

//homework F
class Ff : public Function{
private:
    double A,B,C,E,b;
public:
    Ff(double l,double h ,double D,double beta)
    {
        b = beta/180*pi;
        A = l* sin(b);
        B = l* cos(b);
        C = (h + 0.5*D)*sin(b)-0.5*D*tan(b);
        E = (h+0.5*D)*cos(b)-0.5*D;
    }

    double operator()(const double &x) const {
        return A*sin(x)*cos(x) + B*sin(x)*sin(x)
            -C*cos(x)-E*sin(x);

    }

    double diff(const double &x) const{
        return A*(cos(x)*cos(x)-sin(x)*sin(x))
            +2*B*sin(x)*cos(x)+C*sin(x)-E*cos(x);
    }

};

void test_f_1(){
    Ff f_f_1(89,49,55,11.5);
    NewtonSolver solver(33.0/180*pi,f_f_1);
    double root = solver.solve();
    cout << " Programme F" <<endl;
    cout << " alpha = " << root/pi*180 << " degree" <<endl;
}

void test_f_2(){
    Ff f_f_2(89,49,30,11.5);
    NewtonSolver solver2(33.0/180*pi,f_f_2);
    double root2 = solver2.solve();
    cout << " alpha = " << root2/pi*180 << " degree" <<endl;
}

void test_f_3(){
    Ff f_f_3(89, 49, 55 ,11.5);
    SecandSolver solver(33.0/180*pi,30.0/180*pi, f_f_3);
    double ans1 = solver.solve();
    cout << " alpha = " << ans1/pi*180 << " degree" <<endl;

    SecandSolver solver2(33.0/180*pi,120.0/180*pi, f_f_3);
    double ans2 = solver2.solve();
    cout << " alpha = " << ans2/pi*180 << "degree" <<endl;

    SecandSolver solver3(155.0/180*pi,pi, f_f_3);
    double ans3 = solver3.solve();
    cout << " alpha = " << ans3/pi*180 << "degree" <<endl;
}
int main()
{
     //B
    test1();
    test2();
    test3();
    test4();

    //C
    test_c_1();

    //D
    test_d_1();
    test_d_2();
    test_d_3();

    //E
    test_e();

    //F
    test_f_1();
    test_f_2();
    test_f_3();
    


}